#ifndef __GAME_LOG_H__
#define __GAME_LOG_H__

#include "game_def.h"
#include <stdarg.h>
#include <string>
#include <vector>
extern "C" {
#include <log4c.h>
}
#include <map>

static const int C_MAX_LOG = 16 * 1024;


#define C_TRACE(format,...) __trace(format, ##__VA_ARGS__)
#define CC_TRACE(name,format, ...) __cctrace(name,format, ##__VA_ARGS__)
#define C_DEBUG(format,...) __debug(format, ##__VA_ARGS__)
#define CC_DEBUG(name,format, ...) __ccdebug(name,format, ##__VA_ARGS__)
#define C_LOG(format, ...) __log(format, ##__VA_ARGS__)
#define CC_LOG(name,format, ...) __cclog(name,format, ##__VA_ARGS__)
#define C_WARN(format,...) __warn(format, ##__VA_ARGS__)
#define CC_WARN(name,format, ...) __ccwarn(name,format, ##__VA_ARGS__)
#define C_ERROR(format,...) __error(format, ##__VA_ARGS__)
#define CC_ERROR(name,format, ...) __ccerror(name,format, ##__VA_ARGS__)
#define C_FATAL(format,...) __fatal(format, ##__VA_ARGS__)
#define CC_FATAL(name,format, ...) __ccfatal(name,format, ##__VA_ARGS__)


void __trace(const char * format, ...);
void __cctrace(const char* name,const char* format,va_list a_args);
void __cctrace(const char* name,const char* format, ...);
void __debug(const char * format, ...);
void __ccdebug(const char* name,const char* format,va_list a_args);
void __ccdebug(const char* name,const char* format, ...);
void __log(const char * format, ...);
void __cclog(const char* name,const char* format,va_list a_args);
void __cclog(const char* name,const char* format, ...);
void __warn(const char * format, ...);
void __ccwarn(const char* name,const char* format,va_list a_args);
void __ccwarn(const char* name,const char* format, ...);
void __error(const char * format, ...);
void __ccerror(const char* name,const char* format,va_list a_args);
void __ccerror(const char* name,const char* format, ...);

void __fatal(const char * format, ...);
void __ccfatal(const char* name,const char* format,va_list a_args);
void __ccfatal(const char* name,const char* format, ...);

const char *__log4c_foramt(const log4c_layout_t *a_layout, const log4c_logging_event_t *a_event);
log4c_appender_t* __log4c_appender_get(log4c_layout_t* layout);
log4c_layout_t* __log4c_layout_get();

class CGameLoggerFactory;
class CGameLogger;


namespace CGame{
namespace Logger{
  typedef std::map<std::string,CGameLogger*> logger_map_t;
  typedef log4c_priority_level_t PriorityLevel_t;
  std::string priorityToStr(PriorityLevel_t priority);
  PriorityLevel_t priorityFromStr(std::string priority);
}
}

class CGameLogger : public CGameObject{
protected:
  std::string _name;
  log4c_category_t* _logCategory;

protected:
  CGameLogger(){};
  CGameLogger(const char* name){
    _name.assign(name);
  };

  CGame::Logger::PriorityLevel_t _priority;
  friend class CGameLoggerFactory;
public:
  const std::string& name(){
    return _name;
  }
  virtual BOOL init(CGame::Logger::PriorityLevel_t _priority);
  virtual void trace(const char * format, ...);
  virtual void trace(const char * format,va_list a_args);
  virtual void warn(const char * format, ...);
  virtual void warn(const char * format,va_list a_args);
  virtual void error(const char * format, ...);
  virtual void error(const char * format,va_list a_args);
  virtual void debug(const char * format, ...);
  virtual void debug(const char * format,va_list a_args);
  virtual void info(const char * format, ...);
  virtual void info(const char * format,va_list a_args);
  virtual void fatal(const char * format, ...);
  virtual void fatal(const char * format,va_list a_args);

  BOOL isDebugEnabled() const{
    return log4c_category_is_debug_enabled(_logCategory) ? TRUE:FALSE;
  };

  /**
   * @brief
   *
   * @param priority
   */
  virtual void priority(CGame::Logger::PriorityLevel_t priority){
    setPriority(priority);
  }
  virtual void setPriority(CGame::Logger::PriorityLevel_t priority);
  CGame::Logger::PriorityLevel_t getPriority(){
    return _priority;
  }
};



class CGameLoggerFactory:public CGameObject{
private:
  CGame::Logger::logger_map_t _maps;
  static CGameLoggerFactory* _ins;
  CGame::Logger::PriorityLevel_t _priority;
protected:
  log4c_layout_t* _log4c_layout;
  log4c_appender_t* _log4c_appender;
  // friend void __logger_init(CGameLogger* logger,CGameLoggerFactory* factory);
  // friend CGameLoggerFactory* __logger_factory_get();
  CGame::Logger::PriorityLevel_t getPriority(){
    return _priority;
  }
  virtual CGameLogger* newLogger(const std::string& name);
public:
  virtual BOOL init();
  virtual BOOL init(CGame::Logger::PriorityLevel_t priority);
  CGameLogger* getLogger(const std::string& name);
  std::vector<std::string> getLoggerList();

  static CGameLoggerFactory* getInstance();


};

namespace CGame{
namespace Logger{

int __log4c_appender_type_file_open(log4c_appender_t *a_appender);
int __log4c_appender_type_file_close(log4c_appender_t *a_appender);
int __log4c_appender_type_file_append(log4c_appender_t *a_appender, const log4c_logging_event_t *a_event);



class StdoutLoggerFactory:public CGameLoggerFactory{
private:
  // static StreamLoggerFactory* ins;
  // friend CGameLoggerFactory* __logger_factory_get();
public:
  virtual BOOL init();
};

class FileLoggerFactory:public CGameLoggerFactory{


protected:

  friend int __log4c_appender_type_file_open(log4c_appender_t *a_appender);
  friend int __log4c_appender_type_file_close(log4c_appender_t *a_appender);
  friend int __log4c_appender_type_file_append(log4c_appender_t *a_appender, const log4c_logging_event_t *a_event);


  virtual const char* getFilename() = 0;
  virtual int open() = 0;
  virtual int append(const log4c_logging_event_t *a_event) = 0;
  virtual int close() = 0;
public:
  virtual BOOL init();
};

}}



#endif
